﻿using Application.Adapter;
using Domain.Models;
using Domain;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TouchSocket.Core;
using TouchSocket.Sockets;
using Domain.Options;
using Newtonsoft.Json;
using System.Net.Http;
using Microsoft.Extensions.Options;
using System.Diagnostics;

namespace Application.Plugins
{
    public class DeviceStateHandlerPlugin : PluginBase, ITcpReceivedPlugin<ISocketClient>, ITcpConnectedPlugin<ISocketClient>
    {
        private readonly IHttpClientFactory _httpClientFactory;
        private readonly ApiConfigOptions apiConfigOptions;
        public DeviceStateHandlerPlugin(IHttpClientFactory httpClientFactory, IOptions<ApiConfigOptions> options)
        {
            _httpClientFactory = httpClientFactory;
            apiConfigOptions = options.Value;
        }
        public Task OnTcpConnected(ISocketClient client, ConnectedEventArgs e)
        {
            return Task.CompletedTask;
        }

        public Task OnTcpReceived(ISocketClient client, ReceivedDataEventArgs e)
        {
            Console.WriteLine(nameof(DeviceStateHandlerPlugin));
            if (e.RequestInfo is BetweenAndRequestInfo myRequest)
            {
                //验证校验码
                if (!myRequest.VaildSuccess)
                {
                    Console.WriteLine("未通过验证码校验，拒绝处理"+Convert.ToHexString(myRequest.Body));
                    return Task.CompletedTask;
                }
                var socketId = string.Empty;
                var deviceIdStr = Convert.ToHexString(myRequest.DeviceId);
                //如果上行   更新最后一个通信id索引为设备socket
                if (myRequest.DataType.ToString().EndsWith("上"))
                {
                    //是首次链接  或者断开重连
                    if (!Consts.DeviceToSocketId.ContainsKey(deviceIdStr) || client.Id != Consts.DeviceToSocketId[deviceIdStr])
                    {
                        try
                        {
                            var callData = new DeviceStateCall
                            {
                                device = deviceIdStr,
                                state = 100
                            };
                            Console.WriteLine($"{DateTime.Now:yyyy-MM-dd HH:mm:ss} PostAsync:" + JsonConvert.SerializeObject(callData));
                            using (var httpClient = _httpClientFactory.CreateClient("BaseCallBackUrl"))
                            {
                                httpClient.PostAsync(apiConfigOptions.StateUpdateUrl, new StringContent(JsonConvert.SerializeObject(callData), Encoding.UTF8, "application/json")).Wait();
                            }
                        }
                        catch (Exception)
                        {
                            Console.WriteLine($"{deviceIdStr}首次连接回调失败");
                        }
                    }

                    Consts.DeviceToSocketId.TryAdd(deviceIdStr, client.Id);
                    Consts.DeviceToSocketId[deviceIdStr] = client.Id;
                    Consts.devices.TryAdd(deviceIdStr, new Device());
                    Consts.devices[deviceIdStr].ScoketIPPort = client.IP + ":" + client.Port;
                    Consts.devices[deviceIdStr].State = 1;
                    Consts.devices[deviceIdStr].LastUpCmdTime = DateTime.UtcNow.AddHours(8);
                    Console.WriteLine(deviceIdStr + "设备加入socketClient,id:" + client.Id);

                    //打印上行所有命令数据
                    Console.WriteLine(myRequest.DataType.ToString() + " data " + Convert.ToHexString(myRequest.Body));


                    var upData = new DeviceStateCall
                    {
                        device = deviceIdStr,
                        state = 101
                    };

                    Console.WriteLine($"{DateTime.Now:yyyy-MM-dd HH:mm:ss} PostAsync:" + JsonConvert.SerializeObject(upData));
                    using (var httpClient = _httpClientFactory.CreateClient("BaseCallBackUrl"))
                    {
                        httpClient.PostAsync(apiConfigOptions.StateUpdateUrl, new StringContent(JsonConvert.SerializeObject(upData), Encoding.UTF8, "application/json")).Wait();
                    }
                }
            }
            return e.InvokeNext();
        }
    }
}
